package com.ruoyi.HKISAPI.utils;



import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.ruoyi.HKISAPI.controller.ImageController;
import com.ruoyi.HKISAPI.controller.ImageDownloader;
import com.ruoyi.HKISAPI.demo.entity.enums.ContentTypeEnum;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.electronicFence.domain.TEfAlarm;
import com.ruoyi.electronicFence.domain.TEfAlarms;
import com.ruoyi.electronicFence.domain.TEfEquipmentDevice;
import com.ruoyi.electronicFence.service.ITEfAlarmService;
import com.ruoyi.electronicFence.service.ITEfAlarmsService;
import com.ruoyi.electronicFence.service.ITEfEquipmentDeviceService;
import com.ruoyi.rsikManage.domain.MonitorPoint;
import com.ruoyi.rsikManage.domain.TVcrData;
import com.ruoyi.rsikManage.service.ITVcrDataService;
import com.ruoyi.rsikManage.service.MonitorPointService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 报警事件解析处理逻辑
 */

@Slf4j
@Component
public class AlarmDataParser {

    /**
     * 解析数据
     *
     * @param contentType   要解析的类型
     * @param storeFolderPath 保存文件路径
     * @param alarmInfo
     * @param byteArray
     */

    @Value("${hk.imageURL}")
    private String imageURL;
    private static MonitorPointService monitorPointService;

    @Autowired
    public void setMonitorPointService(MonitorPointService monitorPointService) {
        AlarmDataParser.monitorPointService = monitorPointService;
    }
    private static ITEfAlarmsService tEfAlarmsService;

    @Autowired
    public void setITEfAlarmsService(ITEfAlarmsService tEfAlarmsService) {
        AlarmDataParser.tEfAlarmsService = tEfAlarmsService;
    }

    private static ITEfAlarmService tEfAlarmService;
    @Autowired
    public void setITEfAlarmService(ITEfAlarmService tEfAlarmService) {
        AlarmDataParser.tEfAlarmService = tEfAlarmService;
    }


    private static ITVcrDataService iTVcrDataService;
    @Autowired
    public void setITVcrDataService(ITVcrDataService iTVcrDataService) {
        AlarmDataParser.iTVcrDataService = iTVcrDataService;
    }

    private static ITEfEquipmentDeviceService iTEfEquipmentDeviceService;
    @Autowired
    public void setITEfEquipmentDeviceService(ITEfEquipmentDeviceService iTEfEquipmentDeviceService) {
        AlarmDataParser.iTEfEquipmentDeviceService = iTEfEquipmentDeviceService;
    }

    private static ImageDownloader imageDownloader;
    @Autowired
    public void setImageDownloader(ImageDownloader imageDownloader) {
        AlarmDataParser.imageDownloader = imageDownloader;
    }


//
//    @Autowired
//    private MonitorPointService monitorPointService;

//    @Autowired
//    private ITEfAlarmsService tEfAlarmsService;

//    public AlarmDataParser(ITEfAlarmsService iTEfAlarmsService, MonitorPointService monitorPointService) {
//        this.iTEfAlarmsService = iTEfAlarmsService;
//        this.monitorPointService = monitorPointService;
//    }


    public void parseAlarmInfo(int contentType, String storeFolderPath, String alarmInfo, byte[] byteArray) {
        String curTimeStampStr = TimeFormatUtil.curTimeFormat();

        // 非二进制类型的数据处理
        if (alarmInfo != null) {
            switch (contentType) {
                case ContentTypeEnum.APPLICATION_JSON:
                case ContentTypeEnum.APPLICATION_XML: {
                    handleAlarmBodyInfo(storeFolderPath, curTimeStampStr, contentType, alarmInfo);
                    break;
                }
            }
        }

        // 二进制的数据信息
        if (byteArray != null) {
            handleByteAryFile(storeFolderPath, curTimeStampStr, contentType, byteArray);
        }
    }

    /**
     * 处理报警事件数据内容
     *
     * @param storeFolderPath
     * @param alarmInfo
     */
    private void handleAlarmBodyInfo(String storeFolderPath, String curTimestamp, int contentType, String alarmInfo) {
        String eventType = "";
        String dateTime = "";
        String ipAddress = "";
        String channelID = "";
        String bkgUrl = "";

        log.info("tEfAlarmsService: {}", tEfAlarmsService);
        log.info("monitorPointService: {}", monitorPointService);

        try {
            // TODO 这里需要根据实际的业务逻辑自行处理下报警事件报文结构体类型，根据eventType进行处理
            switch (contentType) {
                case ContentTypeEnum.APPLICATION_JSON: {
                    // 使用 com.alibaba.fastjson.JSONObject 的方式来处理
                    JSONObject jsonAlarmRecv = JSONObject.parseObject(alarmInfo);
                    eventType = jsonAlarmRecv.get("eventType").toString();
                    dateTime = jsonAlarmRecv.get("dateTime").toString();
                    ipAddress = jsonAlarmRecv.get("ipAddress").toString();
                    channelID = jsonAlarmRecv.get("channelID").toString();
                    bkgUrl = jsonAlarmRecv.get("bkgUrl").toString();
                    break;
                }
                case ContentTypeEnum.APPLICATION_XML: {
                    // 注意： 实际设备上报的是xml格式的数据，这里借助工具类转换为Json格式的数据，仅供demo参考用
                    JSONObject xmlObj  = convertXmlToJson(alarmInfo);
                    Map<String, Object> xmlObjMap = convertXmlToJsonMap(alarmInfo);
                    eventType = xmlObjMap.get("eventType").toString();
                    dateTime = xmlObjMap.get("dateTime").toString();
                    ipAddress = xmlObjMap.get("ipAddress").toString();
                    channelID = xmlObjMap.get("channelID").toString();
                    bkgUrl = xmlObjMap.get("bkgUrl").toString();
                    if (eventType.equals("fielddetection")){
                        insertEFAlarms(xmlObjMap);
                        insertEFAlarm(xmlObjMap);

                    }
                    break;
                }
                default: {
                    System.out.println("未匹配到可以解析的content-type, 请自行处理！");
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }


        System.out.println("eventType: " + eventType +
                "\ndateTime: " + dateTime +
                "\nipAddress: " + ipAddress +
                "\nchannelID: " + channelID +
                "\nbkgUrl: " + bkgUrl);
        String filename = curTimestamp + "_eventType_" + eventType;

        // 保存报警报文内容到文件中 2024-07-03 取消保存
        //FileUtil.output2File(storeFolderPath, filename, ContentTypeEnum.getFilePostfix(contentType), alarmInfo);
    }


    /**
     * 处理byte数组到文件
     *
     * @param storeFolderPath
     * @param ch
     */
    private static void handleByteAryFile(String storeFolderPath, String curTimestamp, int contentType, byte[] ch) {
        // 保存byte数组数据到文件中
        FileUtil.byteAry2File(storeFolderPath, curTimestamp, ContentTypeEnum.getFilePostfix(contentType), ch);
    }

    public static Map<String, Object> convertXmlToJsonMap(String xml) {
        try {
            // 创建 XmlMapper 对象
            XmlMapper xmlMapper = new XmlMapper();
            // 读取 XML 并将其转换为 JsonNode
            JsonNode node = xmlMapper.readTree(xml.getBytes());

            // 创建 ObjectMapper 对象
            ObjectMapper jsonMapper = new ObjectMapper();
            // 将 JsonNode 转换为 JSON 字符串
            String jsonString = jsonMapper.writeValueAsString(node);
            System.out.println(jsonString);
            // 将 JSON 字符串转换为 Map
            return jsonMapper.readValue(jsonString, Map.class);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static JSONObject convertXmlToJson(String xml) {
        try {
            // 创建 XmlMapper 对象
            XmlMapper xmlMapper = new XmlMapper();
            // 读取 XML 并将其转换为 JsonNode
            JsonNode node = xmlMapper.readTree(xml.getBytes());

            // 创建 ObjectMapper 对象
            ObjectMapper jsonMapper = new ObjectMapper();
            // 将 JsonNode 转换为 JSON 字符串
            String jsonString = jsonMapper.writeValueAsString(node);
//            System.out.println(jsonString);
            // 将 JSON 字符串转换为 Map
            Map map = jsonMapper.readValue(jsonString, Map.class);
            // 将 Map 转换为 JSONObject
            JSONObject jsonObject = new JSONObject(map);
            return jsonObject;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public void  insertEFAlarms(Map<String,Object> map)  {
        TEfAlarms tEfAlarms = new TEfAlarms();
        MonitorPoint monitorPoint = new MonitorPoint();
        String eventType = "";
        String dateTime = "";
        String ipAddress = "";
        String channelID = "";
        String bkgUrl = "";


        eventType = (String)map.get("eventType");
        dateTime = (String)map.get("dateTime");
        ipAddress = (String)map.get("ipAddress");
        channelID = (String)map.get("channelID");
        bkgUrl = (String)map.get("bkgUrl");

        if (eventType.equals("fielddetection")){
            tEfAlarms.setAlarmTypeName("区域入侵侦测");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
        // 将格式化后的字符串转换为 java.util.Date 对象
        try{
            Date date = sdf.parse(dateTime);
            tEfAlarms.setAlarmTime(date);
        }catch (Exception e){

        }
        monitorPoint.setOwnerApsIp(ipAddress);
        monitorPoint.setIdx(channelID);
        List<MonitorPoint> monitorPoints = monitorPointService.selectAllMonitorPoints2(monitorPoint);
        MonitorPoint monitorPoint1 = monitorPoints.get(0);
        tEfAlarms.setDeviceId(monitorPoint1.getApeId());
        tEfAlarms.setDeviceName(monitorPoint1.getName());
        tEfAlarms.setOrgName(monitorPoint1.getOwnerApsName());
        tEfAlarms.setHttpUrl(bkgUrl);

//        tEfAlarms.setAlarmTime(date);
        tEfAlarmsService.insertTEfAlarms(tEfAlarms);


    }

    public void  insertEFAlarm(Map<String,Object> map)  {
        TEfAlarm tEfAlarm = new TEfAlarm();
        MonitorPoint monitorPoint = new MonitorPoint();
        String eventType = "";
        String dateTime = "";
        String ipAddress = "";
        String channelID = "";
        String bkgUrl = "";

        eventType = (String)map.get("eventType");
        dateTime = (String)map.get("dateTime");
        ipAddress = (String)map.get("ipAddress");
        channelID = (String)map.get("channelID");
        bkgUrl = (String)map.get("bkgUrl");

//        if (eventType.equals("fielddetection")){
//            tEfAlarms.setAlarmTypeName("区域入侵侦测");
//        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
        LocalDateTime localDateTime = LocalDateTime.parse(dateTime, formatter);
        try{
            tEfAlarm.setAlarmTime(localDateTime);
        }catch (Exception e){

        }
        monitorPoint.setOwnerApsIp(ipAddress);
        monitorPoint.setIdx(channelID);
        List<MonitorPoint> monitorPoints = monitorPointService.selectAllMonitorPoints2(monitorPoint);
        TVcrData vcrData = new TVcrData();
        LocalDateTime now = LocalDateTime.now();
        MonitorPoint monitorPoint1=new MonitorPoint();
        if (!monitorPoints.isEmpty()){
             monitorPoint1 = monitorPoints.get(0);
//      tEfAlarms.setOrgName(monitorPoint1.getOwnerApsName());
            vcrData.setVcrIp(monitorPoint1.getOwnerApsIp());
            tEfAlarm.setMonitorDeviceId(monitorPoint1.getApeId());
            tEfAlarm.setMonitorDeviceName(monitorPoint1.getName());

        }


        String vcrUsername = "";
        String vcrPassword = "";
        List<TVcrData> tVcrData = iTVcrDataService.selectTVcrDataList(vcrData);
        if(!tVcrData.isEmpty()){
            TVcrData vcrData1 = tVcrData.get(0);
             vcrUsername = vcrData1.getVcrUsername();
             vcrPassword = vcrData1.getVcrPassword();
        }

        String LocalDateTimeStr = getLocalDateTimeStr().get("str");
        Map<String, String> localDateTimeStr = getLocalDateTimeStr();
        String year = localDateTimeStr.get("year");
        String month = localDateTimeStr.get("month");
        String day = localDateTimeStr.get("day");
        String hour = localDateTimeStr.get("hour");
        String minute = localDateTimeStr.get("minute");
        String second = localDateTimeStr.get("second");
        String millisecond = localDateTimeStr.get("millisecond");
        try{


            String  downloadImagePath="";
            //mac版本测试
             downloadImagePath = "D:" + File.separator + "ef" +  File.separator + "image" + File.separator + LocalDateTimeStr + "_" + eventType + ".jpg";

// 注意：无需手动替换分隔符，File.separator会自动使用正确的分隔符
            System.out.println(downloadImagePath);
//            downloadImagePath="/Users/wangxiaoxing/Desktop/sql/"+LocalDateTimeStr+"_"+eventType+".jpg";
            imageDownloader.downloadImageWithDigestAuth(bkgUrl,vcrUsername,vcrPassword,downloadImagePath);

        }catch (Exception e){
            System.out.println("图片下载异常");
        }
//        downloadImage(bkgUrl,"admin","sxygsj123","/Users/wangxiaoxing/Desktop/sql/"+now+".jpg");
        //添加硬盘录像机信息
       String StoragePath ="http://172.16.15.200:86"+"/ef/image/"+year+"_"+month+"/"+day+"/"+hour+"_"+minute+"_"+second+"_"+millisecond+"_"+eventType+".jpg";
        tEfAlarm.setPictureUrl(StoragePath);
     ;
        TEfEquipmentDevice tEfEquipmentDevice = new TEfEquipmentDevice();
        tEfEquipmentDevice.setDeviceId(monitorPoints.get(0).getApeId());
        //添加场景信息
        List<TEfEquipmentDevice> tEfEquipmentDevices = iTEfEquipmentDeviceService.selectTEfEquipmentDeviceList(tEfEquipmentDevice);
        if (!tEfEquipmentDevices.isEmpty()) {
            TEfEquipmentDevice tEfEquipmentDevice1 = tEfEquipmentDevices.get(0);
            tEfAlarm.setMonitorDeviceType(tEfEquipmentDevice1.getDeviceType());
            tEfAlarm.setPlaceType(tEfEquipmentDevice1.getAreaType());
            tEfAlarm.setAlarmArea(tEfEquipmentDevice1.getAreaName());
        }

        tEfAlarm.setControllerName(monitorPoint1.getName());
//      tEfAlarms.setAlarmTime(date);
        tEfAlarmService.insertTEfAlarm(tEfAlarm);

    }
    public static void downloadImage(String imageUrl, String username, String password, String destinationFile) {
        try{
            URL url = new URL(imageUrl);

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        // 设置 Digest 认证信息
        conn.setRequestProperty("Authorization", getDigestAuthHeader(username, password, conn));

        try (InputStream in = new BufferedInputStream(conn.getInputStream());
             FileOutputStream out = new FileOutputStream(destinationFile)) {

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }catch (Exception e){

        }
    }catch (Exception e){

        }
    }
    // 计算 Digest 认证头部
    private static String getDigestAuthHeader(String username, String password, HttpURLConnection conn) throws IOException {
        String realm = conn.getHeaderField("WWW-Authenticate");
        String nonce = parseParameter("nonce", realm);
        String qop = parseParameter("qop", realm);
        String algorithm = parseParameter("algorithm", realm);
        String uri = conn.getURL().getPath();

        String HA1 = calculateMD5(username + ":" + realm + ":" + password);
        String HA2 = calculateMD5("GET:" + uri);

        String response = calculateMD5(HA1 + ":" + nonce + ":00000001:xyz:" + qop + ":" + HA2);

        return "Digest username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", uri=\"" + uri + "\", response=\"" + response + "\"";
    }

    // 计算 MD5 散列值
    private static String calculateMD5(String data) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(data.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b & 0xff));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }
    // 解析 Digest 认证返回的参数
    private static String parseParameter(String paramName, String realm) {
        // 省略实现，根据 paramName 解析 realm 中的参数值
        return ""; // 需要根据具体情况实现
    }
    public static void main(String[] args){
        getLocalDateTimeStr();
    }
    private static Map<String,String>  getLocalDateTimeStr(){

        String str="";
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();

        // 提取年、月、日、时、分、秒
        int year = now.getYear();
        int month = now.getMonthValue();
        int day = now.getDayOfMonth();
        int hour = now.getHour();
        int minute = now.getMinute();
        int second = now.getSecond();

        // 计算毫秒数
        long nano = now.getNano();
        int millisecond = (int)(nano / 1_000_000);

        // 创建Map并填充
        Map<String, String> map = new HashMap<>();

        // 转换为字符串并放入Map
        String yearStr = String.valueOf(year);
        map.put("year", yearStr);

        String monthStr = String.valueOf(month);
        map.put("month", monthStr);

        String dayStr = String.valueOf(day);
        map.put("day", dayStr);

        String hourStr = String.valueOf(hour);
        map.put("hour", hourStr);

        String minuteStr = String.valueOf(minute);
        map.put("minute", minuteStr);

        String secondStr = String.valueOf(second);
        map.put("second", secondStr);

        String millisecondStr = String.valueOf(millisecond);
        map.put("millisecond", millisecondStr);




        str=yearStr+"_"+monthStr+File.separator+dayStr+File.separator+hourStr+"_"+minuteStr+"_"+secondStr+"_"+millisecondStr;
        System.out.println(str);
        map.put("str",str);
        return map;
    }

}
